-----Verified and Tested---------------------------------------------------------------------
-- Company: 
-- Engineer: 		Sneha Nidhi
-- 
-- Create Date:    14:58:10 01/16/2011 
-- Design Name: 
-- Module Name:    DMA - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
USE work.LCSE.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity DMA is

PORT (
   Reset     : in  std_logic;--asynchronous reset
   Clk       : in  std_logic;--20 MHZ
   
	----------------recieve data from rs232 to dma--------------------------------
   RCVD_Data : in  std_logic_vector(7 downto 0);--
	RX_Full   : in  std_logic;--status signal RX internal memory full--from rs232 to dma
									--RX_Empty=0 fifo is full.then rs232 tx data to dma
	RX_Empty  : in  std_logic;--status signal RX internal memory ---------from rs232 to dma
	Data_Read : out  std_logic;--request to read data from the rs232
   
	--------------------transmit data from dma to rs 232------------------------------
	TX_RDY    : in  std_logic;--state of machine serial tx
	ACK_out   : in  std_logic;--ack for data rx from rs 232..data from rs232 to pc
	Valid_D   : out  std_logic;--valid data sent to rs232TX
   TX_Data   : out  std_logic_vector(7 downto 0);--send data to serial line
   
   -------------RAM------------------------------------------------------
	CS        : out  std_logic;--chip select
   Write_en  : out  std_logic;---write data to ram 
   OE        : out  std_logic;--read  from ram
   Address   : out  std_logic_vector(7 downto 0); --address bus
	Databus   : inout  std_logic_vector(7 downto 0); --system data bus
	
	-----main control-----------------------------------------
	DMA_ACK   : in  std_logic; --recognition and sharing of buses by the main processor
   Send_comm : in  std_logic; --start of data tx
	DMA_RQ    : out  std_logic; --request for bus to the processor
   READY     : out  std_logic  ---=1 when processor is idle, 0-> processor is busy 
	);
end DMA;

architecture Behav of DMA is
	
	type state is (idle,bus_control,wr_ram,transmit);
	signal current_state, next_state: state;
--signals--------------------------------------------
	signal Data_Read_s : std_logic;	--connects rs322 n dma
	signal Valid_D_s : std_logic;--connects rs232 n dma 
	signal TX_Data_s : std_logic_vector(7 downto 0);--connects dma to databus n writes to the address location
	signal DMA_RQ_s  : std_logic;--DMA_RQ
	signal READY_s   : std_logic;--READY
	signal rst_rx_counter: std_logic;--reset the rx counter
	signal rst_tx_counter: std_logic;--reset the rx counter
	signal en_tx_counter: std_logic;--enable the counter
	----------------------------------------------------
	signal rx_counter,tx_counter: integer;
	signal Databus_OE: std_logic;
	signal Address_OE: std_logic;
	signal Databus_i: std_logic_vector(7 downto 0);
	signal Address_i: std_logic_vector(7 downto 0);
begin

Databus <= Databus_i WHEN Databus_OE = '1' ELSE ("ZZZZZZZZ");
Address <= Address_i WHEN Address_OE = '1' ELSE ("ZZZZZZZZ");

dma_controller: process(Reset,current_state, RCVD_Data, RX_Empty,ACK_out,Databus, TX_RDY, DMA_ACK, Send_comm,rx_counter,tx_counter)

begin

	next_state<= current_state;
--------default assignments----------------			
		Data_Read_s 		<= '0' after 1 ns;--no read req to rs232
		Valid_D_s 			<= '1' after 1 ns;---active low signal--no load new data...tx in progress
		TX_Data_s 			<= (others =>'0') after 1 ns;
		DMA_RQ_s 			<= '0' after 1 ns;--no req for bus
		CS 					<= '0' ;--high impedence--not in use
		Write_en 			<= '0' after 1 ns;--high impedence--not in use
		OE			 			<= '0' after 1 ns;--high impedence--not in use
		READY_s 				<= '1' after 1 ns;--busy bus-- not ready to giv the acces to main control to tx
		Databus_OE 			<='0' after 1 ns;--not in use
		Address_OE 			<='0' after 1 ns;--not in use
		rst_rx_counter		<='0' after 1 ns;
		rst_tx_counter		<='0' after 1 ns;
		en_tx_counter		<='0' after 1 ns;
		Databus_i 			<= (others =>'0') after 1 ns;
		Address_i 			<= (others =>'0') after 1 ns;
---------------------------------------------
if (Reset='0') then
		next_state <= idle after 1 ns;	
else
	case current_state is 
											-----receive the instructions from the rs232 and store in the registers-----------			
			
	when idle =>			 			--idle state no function
											-------end of rx from rs232---all the 3 bytes have been recieved------------		
		if (rx_counter = 3)then 	---3 instruction bytes have been received
			Write_en <= '1' after 1 ns;			--write enable 
			--OE <= '0' after 1 ns;         		-- read disabled
			Address_OE <='1';
			Address_i <= NEW_INST after 1 ns;		-- end of the transmission
			Databus_OE<='1';
			Databus_i <= X"FF" after 1 ns;
		end if;
																	--RX data from rs232.triggered if there is even min 1 byte present in the buffer
		if(RX_Empty = '0') then								--when fifo is full it triggers the dma to rx data from rs232 
			DMA_RQ_s <= '1' after 1 ns;					--ask for bus control 	
			next_state <= bus_control after 1 ns;		
																	--TX data to rs232-------------		
		elsif(Send_comm='1')then 							--transmit the signal
			READY_s <= '0' after 1 ns;						---bus is transmitting the data
			next_state <=transmit after 1 ns;			
		else 
			next_state <= idle after 1 ns;
		end if;
----------------------------------------------------------------------------------------------------------					
	when bus_control =>										---dma requests for the control of the bus from the processor
		if (rx_counter=3)then 								--the data has been recieved
			next_state <= idle after 1 ns;	
		end if;
																		--rx the data from rs232
		if	(DMA_ACK ='1') then									--dma has the bus control
			READY_s <='0'after 1 ns;							--set the bus as busy
			next_state<= wr_ram after 1 ns;	
			Data_Read_s <='1'after 1 ns;						--  set to read incomin data on bus from rs232
		else 
			DMA_RQ_s <= '1' after 1 ns;
			next_state<= bus_control after 1 ns;
		end if;	
---------------------------------------------------------------------------------------------------------------						
	when wr_ram =>														---write to the ram the 3 bytes in the buffer
		if (rx_counter <3)then
			
			Write_en <= '1' after 1 ns; 									--write in ram			
			--OE <= '0' after 1 ns;      									---no read
			READY_s <='0' after 1 ns;										--busy bus
			next_state<=wr_ram after 1 ns;
			Data_Read_s <='1' after 1 ns;									--set to read incomin data on bus from rs232
				if(rx_counter = 0)then
					Databus_OE<='1';
					Databus_i <= RCVD_Data after 1 ns;
					Address_OE <='1';
					Address_i <= DMA_RX_BUFFER_MSB after 1 ns;			--write to 0x00 location
				elsif(rx_counter = 1)then
					Databus_OE<='1';
					Databus_i <= RCVD_Data after 1 ns;
					Address_OE <='1';
					Address_i <= DMA_RX_BUFFER_MID after 1 ns;			--write to 0x01 location
				elsif(rx_counter = 2)then
					Databus_OE<='1';
					Databus_i <= RCVD_Data after 1 ns;
					Address_OE <='1';
					Address_i <= DMA_RX_BUFFER_LSB after 1 ns;			--write to 0x02 location
				end if;	
		else 																			--all the data has been recieved
			next_state <= idle after 1 ns;	
			rst_rx_counter<='1' after 1 ns;
		end if;	
----------------------------------------------------------------------------------------------------------------------			
	when transmit =>  															---transmission of data from the processor to the pc
		if(TX_RDY = '1') then 													--ready to transmit data from dma 
			--Write_en <= '0' after 1 ns;  										---disable write
			OE <= '1' after 1 ns;												--enable read
			READY_s <='0' after 1 ns;											--busy bus
			Valid_D_s<='0' after 1 ns;											--active low,validate the data--strt tx	
			en_tx_counter<='1' after 1 ns;									--enable counter			
			if (tx_counter=0)then 
				Address_OE <='1';
				Address_i <= DMA_TX_BUFFER_MSB after 1 ns;
				TX_Data_s<= Databus after 1 ns;
				next_state<=transmit after 1 ns;
			elsif(tx_counter=1)then 
				Address_OE <='1';
				Address_i <= DMA_TX_BUFFER_LSB after 1 ns;
				TX_Data_s<= Databus after 1 ns;
				if (ACK_out='1') then 											--active high acknowledgement--sending 2bytes at a time
					next_state<=idle after 1 ns;
				end if;	
			else
				rst_tx_counter<='1' after 1 ns;								--reset the counter
				next_state<=idle after 1 ns;
			end if;
		end if;
	end case;
end if;



end process dma_controller;



clocking: process(Clk)

begin

	if( Clk' event and Clk ='1') then
	
		---output signal------------------
	 Data_Read <= Data_Read_s after 1 ns; 	
	 Valid_D <=Valid_D_s after 1 ns; 
	 TX_Data <=TX_Data_s after 1 ns; 
	 DMA_RQ <=DMA_RQ_s after 1 ns; 
	 READY<=READY_s after 1 ns;

		current_state<= next_state after 1 ns;
		tx_counter<=0 after 1 ns;
		rx_counter<=0 after 1 ns;
																			---------transmit counter-------------------------------	
		if(rst_tx_counter='1') then
			tx_counter<=0 after 1 ns;
		else
			if(en_tx_counter='1')then
				tx_counter<=tx_counter+1 after 1 ns;
			end if;	
		end if;
																			------recieve counter------------------------------------------
		if ((current_state= wr_ram)and(DMA_ACK='1')) then
			if (rst_rx_counter='1') then
				rx_counter<=0 after 1 ns;
			else
				rx_counter<=rx_counter+1 after 1 ns;
			end if;
		end if;
	end if;
end process clocking;

end Behav;

